package com.litt.saap.system.service.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.collections.list.SetUniqueList;

import com.litt.core.dao.page.IPageList;
import com.litt.core.dao.ql.PageParam;
import com.litt.saap.core.common.SaapConstants.RoleStatus;
import com.litt.saap.core.module.bizrole.config.BizroleModuleConfig;
import com.litt.saap.core.module.bizrole.config.BizrolePermConfig;
import com.litt.saap.core.module.bizrole.config.BizrolePermConfigManager;
import com.litt.saap.core.web.util.LoginUtils;
import com.litt.saap.system.dao.BizRoleDao;
import com.litt.saap.system.dao.BizRoleDataPermissionDao;
import com.litt.saap.system.dao.BizRoleFieldPermissionDao;
import com.litt.saap.system.dao.BizRoleMemberDao;
import com.litt.saap.system.dao.RoleFuncPermissionDao;
import com.litt.saap.system.po.BizRole;
import com.litt.saap.system.po.BizRoleDataPermission;
import com.litt.saap.system.po.BizRoleFieldPermission;
import com.litt.saap.system.po.BizRoleMember;
import com.litt.saap.system.po.Role;
import com.litt.saap.system.service.IBizRoleService;

/**
 * .
 * 
 * <pre><b>描述：</b>
 *    
 * </pre>
 * 
 * <pre><b>修改记录：</b>
 *    
 * </pre>
 * 
 * @author <a href="mailto:littcai@hotmail.com">蔡源</a>
 * @since 2013-11-14
 * @version 1.0
 */
public class BizRoleServiceImpl implements IBizRoleService {
	
	@Resource
	private BizRoleDao bizRoleDao;
	@Resource
	private BizRoleMemberDao bizRoleMemberDao;
	@Resource
	private RoleFuncPermissionDao roleFuncPermissionDao;
	@Resource
	private BizRoleFieldPermissionDao bizRoleFieldPermissionDao;
	@Resource
	private BizRoleDataPermissionDao bizRoleDataPermissionDao;
	
	/* (non-Javadoc)
	 * @see com.litt.saap.system.service.impl.IRoleService#save(com.litt.saap.system.po.Role)
	 */
	public BizRole save(BizRole role, String[] moduleCodes, String[] fields)
	{		
		role.setCreateBy(LoginUtils.getLoginOpId().intValue());
		role.setCreateDatetime(new Date());
		role.setUpdateBy(role.getCreateBy());
		role.setUpdateDatetime(role.getCreateDatetime());
		
		Integer roleId = bizRoleDao.save(role);
		
		Map<String, String> permMap = new HashMap<String, String>();
		if(null != fields && fields.length > 0){
			for(String field : fields){
				String[] arr = field.split("-");
				String fieldsStr = permMap.get(arr[0]);
				if(null == fieldsStr || "".equals(fieldsStr)){
					permMap.put(arr[0], arr[1]);
				}else{
					fieldsStr += "," + arr[1];
					permMap.put(arr[0], fieldsStr);
				}
			}
		}
		
		List<BizRoleFieldPermission> fieldPermissionList = new ArrayList<BizRoleFieldPermission>(permMap.size());
		for (String moduleCode : permMap.keySet()) {
			BizRoleFieldPermission fieldPermission = new BizRoleFieldPermission();
			fieldPermission.setTenantId(role.getTenantId());
			fieldPermission.setBizRoleId(roleId);
			fieldPermission.setModuleCode(moduleCode);
			fieldPermission.setFieldList(permMap.get(moduleCode));
			fieldPermissionList.add(fieldPermission);
		}
		bizRoleFieldPermissionDao.saveBatch(fieldPermissionList);
		
		return role;
	}
	
	/**
	 * Update.
	 * @param role Role
	 */
	public void update(BizRole role, String[] moduleCodes, String[] fields) 
	{
		update(role);
		
		Map<String, String> permMap = new HashMap<String, String>();
		if(null != fields && fields.length > 0){
			for(String field : fields){
				String[] arr = field.split("-");
				String fieldsStr = permMap.get(arr[0]);
				if(null == fieldsStr || "".equals(fieldsStr)){
					permMap.put(arr[0], arr[1]);
				}else{
					fieldsStr += "," + arr[1];
					permMap.put(arr[0], fieldsStr);
				}
			}
		}
		
		List<BizRoleFieldPermission> permissionList = bizRoleFieldPermissionDao.listByTenantAndBizRole(role.getTenantId(), role.getId());
		
		//判重，不存在的删除，新增的追加
		List<BizRoleFieldPermission> delList = new ArrayList<BizRoleFieldPermission>();
		List<BizRoleFieldPermission> newList = new ArrayList<BizRoleFieldPermission>();
		List<BizRoleFieldPermission> uptList = new ArrayList<BizRoleFieldPermission>();
		
		for(BizRoleFieldPermission permission : permissionList){
			String moduleCode = permission.getModuleCode();
			if(permMap.containsKey(moduleCode)){
				permission.setFieldList(permMap.get(moduleCode));
				uptList.add(permission);
			}else{
				delList.add(permission);
			}
			permMap.remove(moduleCode);
		}
		
		for(String moduleCode : permMap.keySet()){
			BizRoleFieldPermission permission = new BizRoleFieldPermission();
			permission.setTenantId(role.getTenantId());
			permission.setBizRoleId(role.getId());
			permission.setModuleCode(moduleCode);
			permission.setFieldList(permMap.get(moduleCode));
			newList.add(permission);
		}
		
		//删除旧的
		roleFuncPermissionDao.deleteBatch(delList);
		//保存新的
		roleFuncPermissionDao.saveBatch(newList);
		//更新
		roleFuncPermissionDao.updateBatch(uptList);
	}

	/**
	 * @param role
	 */
	private void update(BizRole role) {
		//校验租户权限
		LoginUtils.validateTenant(role.getTenantId());
		
		role.setUpdateBy(LoginUtils.getLoginOpId().intValue());
		role.setUpdateDatetime(new Date());
	
		bizRoleDao.update(role);
	}			
   
   	/**
	 * Delete by id.
	 * @param id id
	 */
	public void delete(Integer id) 
	{
		BizRole role = this.load(id);
		
		List<BizRoleMember> memberList = this.listBizRoleMember(role.getTenantId(), role.getId());
		if(null != memberList){
			bizRoleMemberDao.deleteBatch(memberList);
		}
		
		List<BizRoleFieldPermission> permissionList = bizRoleFieldPermissionDao.listByTenantAndBizRole(role.getTenantId(), role.getId());
		if(null != permissionList){
			bizRoleFieldPermissionDao.deleteBatch(permissionList);
		}
		
		this.delete(role);
	}
	
	/**
	 * Batch delete by ids.
	 * @param ids ids
	 */
	public void deleteBatch(Integer[] ids) 
	{
		if(ids!=null)
		{
			for (Integer id : ids) {
				this.delete(id);
			}
		}
	}
	
	/**
	 * Delete by instance.
	 * @param id id
	 */
	public void delete(BizRole role) 
	{
		//校验租户权限
		LoginUtils.validateTenant(role.getTenantId());
	    if(role.getStatus() != RoleStatus.SYSTEM_DEFINED)
	    {
			role.setStatus(RoleStatus.LOGIC_DELETED);
			this.update(role);
	    }
		//roleDao.delete(role);
	}
	
	/**
	 * Load.
	 *
	 * @param roleId the role id
	 * @return the role
	 */
	public BizRole load(int roleId)
	{
		BizRole role = bizRoleDao.load(roleId);
		//校验租户权限
		LoginUtils.validateTenant(role.getTenantId());
	
		return role;
	}
	
	/**
	 * load member by tenant.
	 *
	 * @param tenantId the tenant id
	 * @return the list
	 */
	public BizRole load(int tenantId, String name, int status)
	{
		String hql = "from BizRole where tenantId=? and name=? and status=?";
		return bizRoleDao.uniqueResult(hql, new Object[]{tenantId, name, status}, Role.class);
	}
	
	/**
	 * List by tenant.
	 *
	 * @param tenantId the tenant id
	 * @return the list
	 */
	public List<BizRole> listByTenant(int tenantId)
	{
		String listHql = "from BizRole where tenantId=?";
		return bizRoleDao.listAll(listHql, new Object[]{tenantId});
	}
	
	public List<BizRole> listByTenantAndUser(int tenantId, int userId)
	{
	  String listHql = "select t from BizRole t, BizRoleMember t1 where t.tenantId=? and t.id=t1.bizRoleId and t1.userId=?";
    return bizRoleDao.listAll(listHql, new Object[]{tenantId, userId});
	}
	
	/**
	 * list by page.
	 * 
	 * @param pageParam params
	 * @return IPageList IPageList
	 */
	public IPageList listPage(PageParam pageParam)
	{
		String listHql = "select obj from BizRole obj"
			+ "-- and obj.tenantId={tenantId}"
			+ "-- and obj.name like {name%}"
			;	
		return bizRoleDao.listPage(listHql, pageParam);
	}

	@Override
	public List<Map> findBizRolePermissionTree(int tenantId, Integer bizRoleId) {
		
		BizrolePermConfig config = BizrolePermConfigManager.getInstance().getConfig();
		BizroleModuleConfig[] moduleList = config.getBizroleModuleList();
		
		Map<String, List<String>> groupMap = new HashMap<String, List<String>>();
		if(null != bizRoleId && bizRoleId > 0){
			List<BizRoleFieldPermission> permissionList = bizRoleFieldPermissionDao.listByTenantAndBizRole(tenantId, bizRoleId);
			if(null != permissionList){
				for(BizRoleFieldPermission permission : permissionList){
					String fields = permission.getFieldList();
					String[] fieldsArr = {""};
					if(fields.indexOf(",") > 0){
						fieldsArr = fields.split(",");
					}else{
						fieldsArr[0] = fields;
					}
					groupMap.put(permission.getModuleCode(), Arrays.asList(fieldsArr));
				}
			}
		}
		
		List<Map> nodeList = new ArrayList<Map>();
		for(BizroleModuleConfig module : moduleList){
			Map node = new HashMap();
			node.put("moduleCode", module.getModuleCode());
			List<String> fields = Arrays.asList(module.getFields());
			List<Map> fieldMap = new ArrayList<Map>();
			node.put("fields", fieldMap);
			nodeList.add(node);
			
			List<String> checkedList = groupMap.get(module.getModuleCode());
			if(null != checkedList && checkedList.size() > 0){
				node.put("checked", true);
			}
			for(String field : fields){
				Map subNode = new HashMap();
				subNode.put("field", field);
				if(null != checkedList && checkedList.size() > 0 && checkedList.contains(field)){
					subNode.put("checked", true);
				}
				fieldMap.add(subNode);
			}
			
		}
		
		return nodeList;
	}

	@Override
	public List<BizRoleMember> listBizRoleMember(int tenantId, Integer bizRoleId) {
		String listHql = "from BizRoleMember where tenantId=? and bizRoleId=?";
		return bizRoleMemberDao.listAll(listHql, new Object[]{tenantId, bizRoleId});
	}

	@Override
	public List<BizRoleDataPermission> listBizRoleDataPermission(int tenantId, Integer bizRoleId) {
		String listHql = "from BizRoleDataPermission where tenantId=? and bizRoleId=?";
		return bizRoleDataPermissionDao.listAll(listHql, new Object[]{tenantId, bizRoleId});
	}
	
	@Override
	public List<BizRoleDataPermission> listBizRoleDataPermission(int tenantId, Integer bizRoleId, String fieldName) {
		String listHql = "from BizRoleDataPermission where tenantId=? and bizRoleId=? and fieldName=?";
		return bizRoleDataPermissionDao.listAll(listHql, new Object[]{tenantId, bizRoleId, fieldName});
	}
	
	public String[] findUserDataPermissions(int tenantId, int userId, String fieldName)
	{
	  List<String> retList = SetUniqueList.decorate(new ArrayList<String>());
	  
	  List<BizRole> bozRoleList = this.listByTenantAndUser(tenantId, userId);
	  for (BizRole bizRole : bozRoleList)
    {
	    List<BizRoleDataPermission> rsList = this.listBizRoleDataPermission(tenantId, bizRole.getId(), fieldName);
	    for (int i = 0; i < rsList.size(); i++)
	    {
	      BizRoleDataPermission row = rsList.get(i);
	      retList.add(row.getFieldValue());
	    }
    }
	  return retList.toArray(new String[0]);	  
	}

	@Override
	public void updateBizRoleMember(BizRole role, String[] roleMemberIds) {
		update(role);
		
		List<BizRoleMember> memberList = this.listBizRoleMember(role.getTenantId(), role.getId());
		Map<Integer, BizRoleMember> memberMap = new HashMap<Integer, BizRoleMember>();
		if(null != memberList){
			for(BizRoleMember member : memberList){
				memberMap.put(member.getUserId(), member);
			}
		}
		
		//判重，不存在的删除，新增的追加
		List<BizRoleMember> delList = new ArrayList<BizRoleMember>();
		List<BizRoleMember> newList = new ArrayList<BizRoleMember>();
		
		//new
		for(String roleMemberId : roleMemberIds){
			int memberId = Integer.parseInt(roleMemberId);
			if(!memberMap.containsKey(memberId)){
				BizRoleMember member = new BizRoleMember();
				member.setTenantId(role.getTenantId());
				member.setUserId(memberId);
				member.setBizRoleId(role.getId());
				newList.add(member);
			}
			memberMap.remove(memberId);
		}
		
		//delete
		for(Integer memberId : memberMap.keySet()){
			delList.add(memberMap.get(memberId));
		}
		
		bizRoleMemberDao.deleteBatch(delList);
		bizRoleMemberDao.saveBatch(newList);
	}
	
	@Override
	public void updateBizRoleDataPermission(BizRole role, String data, String fieldName) {
		String[] arr = {""};
		if(data.indexOf(";") > 0){
			arr = data.split(";");
		}else{
			arr[0] = data;
		}
		
		List<BizRoleDataPermission> dpList = this.listBizRoleDataPermission(role.getTenantId(), role.getId(), fieldName);
		Map<String, BizRoleDataPermission> dpMap = new HashMap<String, BizRoleDataPermission>();
		if(null != dpList){
			for(BizRoleDataPermission dp : dpList){
				dpMap.put(dp.getFieldValue() + "," + dp.getFieldName(), dp);
			}
		}
		
		//判重，不存在的删除，新增的追加
		List<BizRoleDataPermission> delList = new ArrayList<BizRoleDataPermission>();
		List<BizRoleDataPermission> newList = new ArrayList<BizRoleDataPermission>();
		
		//new
		for(String dpKey : arr){
			if(!dpMap.containsKey(dpKey)){
				BizRoleDataPermission dp = new BizRoleDataPermission();
				dp.setTenantId(role.getTenantId());
				dp.setBizRoleId(role.getId());
				dp.setFieldValue(dpKey);
				dp.setFieldName(fieldName);
				newList.add(dp);
			}
			dpMap.remove(dpKey);
		}
		
		//delete
		for(String dpKey : dpMap.keySet()){
			delList.add(dpMap.get(dpKey));
		}
		
		bizRoleDataPermissionDao.deleteBatch(delList);
		bizRoleDataPermissionDao.saveBatch(newList);
	}

	/**
	 * Resume by id.
	 * @param id id
	 */
	public void doResume(Integer id) 
	{
		BizRole role = load(id);
		//校验租户权限
		LoginUtils.validateTenant(role.getTenantId());
	    if( role.getStatus()==RoleStatus.LOGIC_DELETED)
	    {
			role.setStatus(RoleStatus.NORMAL);
			this.update(role);
	    }
	}
	
}
